package com.shareach.basic;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.DefaultHttpParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;

import com.benayn.ustyle.logger.Loggers;
import com.mongodb.util.ThreadUtil;
import com.shareach.util.JsonUtil;

public class HttpBase {
	protected final Log log = Loggers.from(getClass());
	private static int timeout = 60000;
	private static int retryCount = 15;
//	private static SimpleHttpConnectionManager connectionManager = null;// MultiThreadedHttpConnectionManager(); 
	static{
//		connectionManager = new SimpleHttpConnectionManager(true);
//		connectionManager.getParams().setSoTimeout(30000);
//		connectionManager.getParams().setConnectionTimeout(10000);
//		connectionManager.getParams().setDefaultMaxConnectionsPerHost(400);
		DefaultHttpParams.getDefaultParams().setParameter(HttpMethodParams.SO_TIMEOUT, timeout);
		DefaultHttpParams.getDefaultParams().setParameter(HttpMethodParams.USER_AGENT, "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.77 Safari/537.1");
        DefaultHttpParams.getDefaultParams().setParameter("http.protocol.cookie-policy", CookiePolicy.BROWSER_COMPATIBILITY);
        
	}
	private static HttpClient getHttpClient(){
//        client = new HttpClient(connectionManager);
		HttpClient client = new HttpClient();
		client.getHttpConnectionManager().getParams().setDefaultMaxConnectionsPerHost(300);
		client.getHttpConnectionManager().getParams().setMaxTotalConnections(400);
        client.getHttpConnectionManager().getParams().setConnectionTimeout(20000);
        return client;
	}

//	static{
//        DefaultHttpParams.getDefaultParams().setParameter("http.protocol.cookie-policy", CookiePolicy.BROWSER_COMPATIBILITY);
//	}
	/**
	 * post Json 格式
	 * @param url
	 * @param obj
	 * @return
	 */
	protected String httpPostJson(String url, Object obj){
		int i=0;
		while(true){
			i++;
			try{
				return internalHttpPostJson(url, obj);
			}catch(Exception exp){
				if(i>retryCount){
					throw new ServiceException(-1,exp.getMessage());
				}
				if(retry(exp.getMessage())){
					log.info(String.format("等待重试：%d次，错误是:%s",i,exp.getMessage()));
					continue;
				}
				throw new ServiceException(-1,exp.getMessage());
			}
		}
	}
	private String internalHttpPostJson(String url, Object obj){
		HttpClient client = null;
		PostMethod post = null;
        try{
	        post = new PostMethod(url);
//	        post.setRequestHeader("User-Agent","Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.77 Safari/537.1");
	        post.setRequestHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
	        post.setRequestHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.3");
	        post.setRequestHeader("Connection", "close");
	        RequestEntity requestEntity = new StringRequestEntity(JsonUtil.jsonFromObject(obj),"application/json","utf-8");
	        post.setRequestEntity(requestEntity);
	        client = getHttpClient();
	        client.executeMethod(post);
			InputStream resStream = post.getResponseBodyAsStream();  
	        BufferedReader br = new BufferedReader(new InputStreamReader(resStream,"utf-8"));  
	        StringBuffer resBuffer = new StringBuffer();  
	        String resTemp = "";  
	        while((resTemp = br.readLine()) != null){  
	            resBuffer.append(resTemp);  
	        }  
	        return resBuffer.toString();  
//	        return post.getResponseBodyAsString();
	        
        }catch(IOException exp){
			throw new ServiceException(-101,"采集错误,"+exp.getMessage());
        }finally {
	    	post.releaseConnection();
	    	((SimpleHttpConnectionManager)client.getHttpConnectionManager()).shutdown();  
	    } 
	}
	
	/**
	 * Post 表单
	 * @param url
	 * @param params
	 * @param heads
	 * @return
	 */
	protected String httpPost(String url, HashMap<String, String> params, HashMap<String, String> heads){

		int i=0;
		while(true){
			i++;
			try{
				return internalHttpPost(url, params, heads);
			}catch(Exception exp){
				if(i>retryCount){
					throw new ServiceException(-1,exp.getMessage());
				}
				if(retry(exp.getMessage())){
					log.info(String.format("等待重试：%d次，错误是:%s",i,exp.getMessage()));
					continue;
				}
				throw new ServiceException(-1,exp.getMessage());
			}
		}
	}
	private String internalHttpPost(String url, HashMap<String, String> params, HashMap<String, String> heads){
		HttpClient client= null;
		PostMethod post = null;
        try{
	        post = new PostMethod(url);
//	        post.setRequestHeader("User-Agent","Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.77 Safari/537.1");
	        post.setRequestHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
	        post.setRequestHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.3");
	        post.setRequestHeader("Connection", "close");
	        if(heads!=null && !heads.isEmpty()){
	        	for(String key : heads.keySet()){
	    	        post.setRequestHeader(key, heads.get(key));
	        	}
	        }
	        post.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"utf-8");  
	        post.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	        if(params!=null && !params.isEmpty()){
	        	for(String key : params.keySet()){
	        		if(StringUtils.isBlank(params.get(key))) continue;
	    	        post.setParameter(key, params.get(key).toString());
	        	}
	        }
	        client = getHttpClient();
	        client.executeMethod(post);
			InputStream resStream = post.getResponseBodyAsStream();  
	        BufferedReader br = new BufferedReader(new InputStreamReader(resStream,"utf-8"));  
	        StringBuffer resBuffer = new StringBuffer();  
	        String resTemp = "";  
	        while((resTemp = br.readLine()) != null){  
	            resBuffer.append(resTemp);  
	        }  
	        return resBuffer.toString();  
//	        return post.getResponseBodyAsString();
        }catch(IOException exp){
			throw new ServiceException(-101,"采集错误,"+exp.getMessage());
        }finally {
	    	post.releaseConnection();
	    	((SimpleHttpConnectionManager)client.getHttpConnectionManager()).shutdown();  
	    }  
	}

	/**
	 * get方法
	 * @param url
	 * @param heads
	 * @return
	 */
	protected String httpGet(String url,  HashMap<String, String> heads){
		int i=0;
		while(true){
			i++;
			try{
				return internalHttpGet(url, heads);
			}catch(Exception exp){
				if(i>retryCount){
					throw new ServiceException(-1,exp.getMessage());
				}
				if(retry(exp.getMessage())){
					log.info(String.format("等待重试：%d次，错误是:%s",i,exp.getMessage()));
					continue;
				}
				throw new ServiceException(-1,exp.getMessage());
			}
		}
	}
	
	private boolean retry(String expMessage){
		if(StringUtils.isBlank(expMessage))return false;
		if(expMessage.indexOf("Connection reset")>-1 ||
		   expMessage.indexOf("No route to host")>-1 ||
		   expMessage.indexOf("Software caused connection abort")>-1 ||
		   expMessage.indexOf("The host did not accept the connection within timeout")>-1) {
			ThreadUtil.sleep(1000);
			return true;
		}
		return false;
	}
	private String internalHttpGet(String url,  HashMap<String, String> heads){
		HttpClient client = null;
		GetMethod get = null;
		try{
			//http://api.map.baidu.com/?qt=bd&c=179&wd=%E6%81%92%E6%99%9F%E5%9B%BE%E6%96%87%20%E6%96%87%E4%B8%89%E8%B7%AF%E5%BA%97&ar=(13372638.45%2C3516228.05%3B13376638.42%2C3520227.95)&rn=10&l=18&ie=utf-8&oue=1&fromproduct=jsapi&res=api
	        get = new GetMethod(url);
//	        get.setRequestHeader("User-Agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17");
	        get.setRequestHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
	        get.setRequestHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.3");
	        get.setRequestHeader("Connection", "close");
	        if(heads!=null && !heads.isEmpty()){
	        	for(String key : heads.keySet()){
	        		get.setRequestHeader(key, heads.get(key).toString());
	        	}
	        }
	        client = getHttpClient();
	        client.executeMethod(get);

			InputStream resStream = get.getResponseBodyAsStream();  
	        BufferedReader br = new BufferedReader(new InputStreamReader(resStream,"utf-8"));  
	        StringBuffer resBuffer = new StringBuffer();  
	        String resTemp = "";  
	        while((resTemp = br.readLine()) != null){  
	            resBuffer.append(resTemp);  
	        }  
	        return resBuffer.toString();  
	    } catch (IOException e) {
	        throw new ServiceException(-1, e.getMessage());
	    } finally {
	    	get.releaseConnection();
	    	((SimpleHttpConnectionManager)client.getHttpConnectionManager()).shutdown();  
	    }   
	}
}
